package com.eastfair.pay.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eastfair.boot.request.PageParams;
import com.eastfair.boot.service.SuperServiceImpl;
import com.eastfair.common.dto.JYApplyRefundDTO;
import com.eastfair.common.dto.JYMainnoResultDTO;
import com.eastfair.common.req.JYReq;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.exception.BizException;
import com.eastfair.core.utils.ConvertUtil;
import com.eastfair.pay.api.FinanceFeign;
import com.eastfair.pay.dao.ApplyRefundMapper;
import com.eastfair.pay.dto.ApplyRefundDTO;
import com.eastfair.pay.dto.ApplyRefundPageQuery;
import com.eastfair.pay.dto.RefundDTO;
import com.eastfair.pay.entity.ApplyRefund;
import com.eastfair.pay.entity.CollectRecord;
import com.eastfair.pay.entity.JyLog;
import com.eastfair.pay.entity.PaymentRecord;
import com.eastfair.pay.entity.Settlement;
import com.eastfair.pay.entity.TransactionOrder;
import com.eastfair.pay.enumeration.TransactionOrderOrderStatusEnum;
import com.eastfair.pay.enums.OrderStateEnum;
import com.eastfair.pay.enums.PayTypeEnum;
import com.eastfair.pay.enums.RefundExamineStateEnum;
import com.eastfair.pay.enums.RefundStatusEnum;
import com.eastfair.pay.enums.RefundTypeEnum;
import com.eastfair.pay.exceptioncode.PayExceptionCode;
import com.eastfair.pay.service.ApplyRefundService;
import com.eastfair.pay.service.ChinaumsLogService;
import com.eastfair.pay.service.CollectRecordService;
import com.eastfair.pay.service.JyLogService;
import com.eastfair.pay.service.JyService;
import com.eastfair.pay.service.MerchantSystemService;
import com.eastfair.pay.service.PaymentRecordService;
import com.eastfair.pay.service.SettlementService;
import com.eastfair.pay.service.TransactionOrderService;
import com.eastfair.pay.vo.ApplyRefundVO;
import com.eastfair.projectcore.enumeration.MenuAffiliationEnum;
import com.eastfair.venuebooking.api.BondManageFeign;
import com.eastfair.venuebooking.api.ExhibitionSettlementFeign;
import com.eastfair.venuebooking.api.ServiceOrderFeign;
import com.eastfair.venueservice.dto.BizStateDTO;
import com.eastfair.venueservice.dto.BondManageDTO;
import com.eastfair.venueservice.dto.ExhibitionSettlementDTO;
import com.eastfair.venueservice.dto.ServiceOrderDTO;
import com.eastfair.venueservice.entity.CreatCode;
import com.eastfair.venueservice.enumeration.ExhibitionSettlementRefundStatusEnum;
import feign.Request;
import io.seata.common.util.CollectionUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 业务实现类
 * 退款申请
 * </p>
 *
 * @author clm
 * @date 2022-06-08
 */
@Slf4j
@Service
public class ApplyRefundServiceImpl extends SuperServiceImpl<ApplyRefundMapper, ApplyRefund> implements ApplyRefundService {

    private static final String REFUND_NUM_FIELD = "refund_num";

    private static final int REFUND_NUM_LENGTH = 5;
    @Autowired
    private SettlementService settlementService;
    @Resource
    private ServiceOrderFeign serviceOrderFeign;
    @Resource
    private TransactionOrderService transactionOrderService;
    @Resource
    private MerchantSystemService merchantSystemService;
    @Value("${com.eastfair.projectId}")
    private Long projectId;

    @Resource
    private FinanceFeign financeService;

    @Resource
    private ApplyRefundMapper applyRefundMapper;

    @Resource
    private JyService jyService;

    @Resource
    private JyLogService jyLogService;

    @Resource
    private ExhibitionSettlementFeign exhibitionSettlementFeign;

    @Resource
    private CollectRecordService collectRecordService;

    @Resource
    private PaymentRecordService paymentRecordService;

    @Resource
    private ChinaumsLogService chinaumsLogService;

    @Resource
    private BondManageFeign bondManageFeign;

    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<ApplyRefund> modelList) {
        modelList.stream().forEach(s -> {
            s.setIsDeleted(BusinessConstant.YES);
        });
        // TODO: 2021/10/29 这里需要操作其他业务，如清空角色等
        return R.successDef();
    }

    /**
     * 处理新增相关处理
     *
     * @param model 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerSave(ApplyRefund model) {
        model.setProjectId(ContextUtil.getProjectId());
        model.setSubsystemId(ContextUtil.getSubSystemId());
        model.setTenantId(ContextUtil.getTenantId());
        return R.successDef();
    }

    /**
     * 退款管理查询
     *
     * @param params
     * @return
     */
    @Override
    public Page<ApplyRefundVO> queryPageList(PageParams<ApplyRefundPageQuery> params) {

        ApplyRefundPageQuery applyRefundPageQuery = params.getModel();

        List<String> scenes = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(applyRefundPageQuery.getSystemScene())) {
            scenes.addAll(applyRefundPageQuery.getSystemScene());
        } else {
            scenes.add(ContextUtil.getSystemScene());
        }
        LambdaQueryWrapper<ApplyRefund> applyRefundLambdaQueryWrapper = new LambdaQueryWrapper<>();
        applyRefundLambdaQueryWrapper.eq(ApplyRefund::getIsDeleted, 0);
//        applyRefundLambdaQueryWrapper.apply("DATE_FORMAT(create_time ,'%Y-%m-%d') <= "+applyRefundPageQuery.getRefundTime());

        //申请时间
        applyRefundLambdaQueryWrapper.ge(applyRefundPageQuery.getStartApplicationTime() != null, ApplyRefund::getCreateTime, applyRefundPageQuery.getStartApplicationTime());
        applyRefundLambdaQueryWrapper.le(applyRefundPageQuery.getEndApplicationTime() != null, ApplyRefund::getCreateTime, applyRefundPageQuery.getEndApplicationTime());
        //退款时间
        applyRefundLambdaQueryWrapper.ge(applyRefundPageQuery.getStartRefundTime() != null, ApplyRefund::getRefundTime, applyRefundPageQuery.getStartRefundTime());
        applyRefundLambdaQueryWrapper.le(applyRefundPageQuery.getEndRefundTime() != null, ApplyRefund::getRefundTime, applyRefundPageQuery.getEndRefundTime());
        //关键字
        applyRefundLambdaQueryWrapper.and(StrUtil.isNotEmpty(applyRefundPageQuery.getKeywords()), likeQueryWrapper -> likeQueryWrapper
                .like(ApplyRefund::getExhibitionName, applyRefundPageQuery.getKeywords())
                .or().like(ApplyRefund::getCutomerName, applyRefundPageQuery.getKeywords())

        );
        applyRefundLambdaQueryWrapper.like(StrUtil.isNotEmpty(applyRefundPageQuery.getRefundClassify()), ApplyRefund::getRefundClassify, applyRefundPageQuery.getRefundClassify());
        applyRefundLambdaQueryWrapper.like(applyRefundPageQuery.getRefundState() != null, ApplyRefund::getRefundState, applyRefundPageQuery.getRefundState());
        applyRefundLambdaQueryWrapper.like(StrUtil.isNotEmpty(applyRefundPageQuery.getRefundUserName()), ApplyRefund::getRefundUserName, applyRefundPageQuery.getRefundUserName());
        applyRefundLambdaQueryWrapper.like(StrUtil.isNotEmpty(applyRefundPageQuery.getBusinessNum()), ApplyRefund::getBusinessNum, applyRefundPageQuery.getBusinessNum());
        applyRefundLambdaQueryWrapper.like(StrUtil.isNotEmpty(applyRefundPageQuery.getRefundNum()), ApplyRefund::getRefundNum, applyRefundPageQuery.getRefundNum());
        applyRefundLambdaQueryWrapper.like(StrUtil.isNotEmpty(applyRefundPageQuery.getExhibitionName()), ApplyRefund::getExhibitionName, applyRefundPageQuery.getExhibitionName());
        applyRefundLambdaQueryWrapper.like(Objects.nonNull(applyRefundPageQuery.getExhibitionId()), ApplyRefund::getExhibitionId, applyRefundPageQuery.getExhibitionId());
        applyRefundLambdaQueryWrapper.like(StrUtil.isNotEmpty(applyRefundPageQuery.getMerchantName()), ApplyRefund::getExhibitionName, applyRefundPageQuery.getExhibitionName());
        applyRefundLambdaQueryWrapper.eq(StrUtil.isNotEmpty(applyRefundPageQuery.getRefundType()), ApplyRefund::getRefundType, applyRefundPageQuery.getRefundType());
        applyRefundLambdaQueryWrapper.eq(applyRefundPageQuery.getRefundState() != null, ApplyRefund::getRefundState, applyRefundPageQuery.getRefundState());
        applyRefundLambdaQueryWrapper.eq(applyRefundPageQuery.getCutomerId() != null, ApplyRefund::getCutomerId, applyRefundPageQuery.getCutomerId());
        applyRefundLambdaQueryWrapper.like(StrUtil.isNotEmpty(applyRefundPageQuery.getCutomerName()), ApplyRefund::getCutomerName, applyRefundPageQuery.getCutomerName());
        applyRefundLambdaQueryWrapper.like(StrUtil.isNotEmpty(applyRefundPageQuery.getBankAccountName()), ApplyRefund::getBankAccountName, applyRefundPageQuery.getBankAccountName());
        applyRefundLambdaQueryWrapper.like(StrUtil.isNotEmpty(applyRefundPageQuery.getBankAccountNum()), ApplyRefund::getBankAccountNum, applyRefundPageQuery.getBankAccountNum());
        applyRefundLambdaQueryWrapper.like(StrUtil.isNotEmpty(applyRefundPageQuery.getBankName()), ApplyRefund::getBankName, applyRefundPageQuery.getBankName());
        applyRefundLambdaQueryWrapper.eq(applyRefundPageQuery.getApplicantId() != null, ApplyRefund::getApplicantId, applyRefundPageQuery.getApplicantId());
        applyRefundLambdaQueryWrapper.like(StrUtil.isNotEmpty(applyRefundPageQuery.getApplicantName()), ApplyRefund::getApplicantName, applyRefundPageQuery.getApplicantName());
        applyRefundLambdaQueryWrapper.like(StrUtil.isNotEmpty(applyRefundPageQuery.getApplicantConcat()), ApplyRefund::getApplicantConcat, applyRefundPageQuery.getApplicantConcat());
        applyRefundLambdaQueryWrapper.eq(StrUtil.isNotEmpty(applyRefundPageQuery.getExamineState()), ApplyRefund::getExamineState, applyRefundPageQuery.getExamineState());
        applyRefundLambdaQueryWrapper.like(StrUtil.isNotEmpty(applyRefundPageQuery.getExaminer()), ApplyRefund::getExaminer, applyRefundPageQuery.getExaminer());
        applyRefundLambdaQueryWrapper.like(StrUtil.isNotEmpty(applyRefundPageQuery.getRefundClassify()), ApplyRefund::getRefundClassify, applyRefundPageQuery.getRefundClassify());
        applyRefundLambdaQueryWrapper.like(StrUtil.isNotEmpty(applyRefundPageQuery.getMerchantName()), ApplyRefund::getMerchantName, applyRefundPageQuery.getMerchantName());
        applyRefundLambdaQueryWrapper.like(StrUtil.isNotEmpty(applyRefundPageQuery.getMerchantBank()), ApplyRefund::getMerchantBank, applyRefundPageQuery.getMerchantBank());
        applyRefundLambdaQueryWrapper.like(StrUtil.isNotEmpty(applyRefundPageQuery.getMerchantBankNum()), ApplyRefund::getApplicantConcat, applyRefundPageQuery.getApplicantConcat());
        applyRefundLambdaQueryWrapper.like(StrUtil.isNotEmpty(applyRefundPageQuery.getBusinessType()), ApplyRefund::getBusinessType, applyRefundPageQuery.getBusinessType());
        applyRefundLambdaQueryWrapper.in(ApplyRefund::getSystemCode, scenes);
        //参数转化
        Page<ApplyRefund> applyRefundPage = params.buildPage();
        //查询
        Page<ApplyRefund> refundPage = page(applyRefundPage, applyRefundLambdaQueryWrapper);
        //实体转化
        Page<ApplyRefundVO> paymentRecordVOPage = ConvertUtil.convertPage(refundPage, ApplyRefundVO.class);

        return paymentRecordVOPage;
    }

    /**
     * 退款保存、修正结算单
     *
     * @param applyRefundDTO
     * @return
     */
    @Override
    public void saveApplyRefund(ApplyRefundDTO applyRefundDTO) {

        if (applyRefundDTO.getRefundApplyAmount().compareTo(new BigDecimal(0)) <= 0) {
            throw BizException.wrap(PayExceptionCode.ZERO_REFUND_NOT_ACCEPT);
        }

        //查询结算单
        Settlement settlement = settlementService.getById(applyRefundDTO.getBusinessId());
        if (null == settlement) {
            throw BizException.wrap(PayExceptionCode.SETTLEMEN_DOCUMENT_DOES_NOT_EXIST);
        }
        //修正已退金额
        settlement.setReturnedAmount(applyRefundDTO.getRefundApplyAmount().add(settlement.getReturnedAmount()));
        //修正结算退款金额
        settlementService.updateById(settlement);
        //对象实例化
        ApplyRefund applyRefund = new ApplyRefund();
        //对象复制
        BeanUtils.copyProperties(applyRefundDTO, applyRefund);
        //赋值
        applyRefund.setCutomerId(settlement.getCutomerId());
        applyRefund.setCutomerName(settlement.getCutomerName());
        applyRefund.setExhibitionId(settlement.getExhibitionId());
        applyRefund.setExhibitionName(settlement.getExhibitionName());
        applyRefund.setApplicantId(ContextUtil.getUserId());
        applyRefund.setApplicantName(ContextUtil.getName());
        applyRefund.setRefundState(RefundStatusEnum.UN_REFUND.getCode());
        applyRefund.setExamineState(RefundExamineStateEnum.APPLIED.getCode());


        applyRefund.setSystemCode(ContextUtil.getSystemScene());
        if (StrUtil.isBlank(applyRefund.getRefundNum())) {
            // 生成订单号
            String prefix = LocalDateTimeUtil.format(LocalDate.now(), "yyyyMMdd");
            String refundNum = CreatCode.creatCode(baseMapper, REFUND_NUM_FIELD, REFUND_NUM_LENGTH, prefix);
            applyRefund.setRefundNum(refundNum);
        }

        //保存退款申请
        save(applyRefund);
        // 同步业务系统
        updateRefundState(applyRefund);

    }

    /**
     * 确认退款
     *
     * @param applyRefundDTO
     * @return
     */
    @Override
    public void saveApplyRefundCnfirm(ApplyRefundDTO applyRefundDTO) {
        //实体转化
        ApplyRefund applyRefund = getById(applyRefundDTO.getId());
        if (applyRefund == null) {
            applyRefund = new ApplyRefund();
        }
        BeanUtils.copyProperties(applyRefundDTO, applyRefund);
        applyRefund.setRefundUserName(ContextUtil.getName());
        applyRefund.setRefundTime(LocalDateTime.now());
        applyRefund.setRefundState(RefundStatusEnum.IS_REFUND.getCode());
        //修改退款
        updateById(applyRefund);

    }

    /**
     * @param applyRefundDTO
     * @return void
     * @Author clm
     * @Description //审核
     * @Date 11:34 2023/2/14
     * @Param [applyRefundDTO]
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateById(ApplyRefundDTO applyRefundDTO) {
        ApplyRefund applyRefund = getById(applyRefundDTO.getId());
        if (applyRefund == null) {
            throw new BizException("退款申请记录不存在");
        }
        log.info("查询退款申请记录,id={} applyRefund={}", applyRefund.getId(), applyRefund);
//        TransactionOrder transactionOrder = transactionOrderService.getByOrderNum(applyRefundDTO.getBusinessNum());
//        if (Objects.isNull(transactionOrder)) {
//            throw new BizException("交易订单不存在");
//        }
        applyRefund.setExamineState(applyRefundDTO.getExamineState());
        applyRefund.setExaminer(applyRefundDTO.getExaminer());
        applyRefund.setExamineId(applyRefundDTO.getExamineId());
        applyRefund.setExamineReason(applyRefundDTO.getExamineReason());
        // 审核通过
        if (RefundExamineStateEnum.AUTH.getCode().equals(applyRefund.getExamineState())) {
            applyRefund.setRefundState(RefundStatusEnum.REFUNDING.getCode());
            //查询订单流水号
            TransactionOrder transactionOrder = transactionOrderService.getByOrderNum(applyRefund.getBusinessNum());
            log.info("查询交易订单成功,transactionOrder={}", transactionOrder);
            if (transactionOrder == null) {
                throw new BizException("交易订单不存在,businessNum=" + applyRefund.getBusinessNum());
            }
            //荆艺退款
            JYReq<JYApplyRefundDTO> req = jyService.buildRefundToJy(applyRefund, transactionOrder);
            log.info("申请荆艺退款入参，req={}", req);
            JyLog jyLog = new JyLog()
                    .setMethodName("申请退款同步")
                    .setTableName(applyRefund.getClass().getName())
                    .setLinkId(String.valueOf(applyRefund.getId()))
                    .setRequestParameter(JSON.toJSONString(req));
            R<List<JYMainnoResultDTO>> result = financeService.sync(req);
            log.info("申请荆艺退款出参，result={}", result);
            jyLog.setResponseResults(JSON.toJSONString(result));
            if (result != null && result.getIsSuccess()) {
                jyLog.setIsSuccess(BusinessConstant.ENABLE_YES);
                if (CollectionUtils.isNotEmpty(result.getData())) {
                    applyRefund.setMainno(result.getData().get(0).getMainno());
                    applyRefund.setRefundState(RefundStatusEnum.REFUNDING.getCode());
                    transactionOrder.setOrderStatus(TransactionOrderOrderStatusEnum.REFUNDING);
                }
            }
            transactionOrderService.updateById(transactionOrder);
            log.info("更新订单状态成功,transactionOrder={}", transactionOrder);
            jyLogService.save(jyLog);
        } else {
            applyRefund.setIsEnabled(BusinessConstant.ENABLE_NO);
        }
        updateById(applyRefund);

        log.info("更新退款申请成功, applyRefund={}", applyRefund);
        updateRefundState(applyRefund);
        log.info("更新退款同步业务系统成功");
    }

    @Override
    public void updateBizRefundState(ApplyRefundDTO applyRefundDTO) {
        // 判断是审核通过还是不通过
        String examineState = applyRefundDTO.getExamineState();
        if (StringUtils.isBlank(examineState)) {
            ApplyRefund refund = getById(applyRefundDTO.getId());
            // 交给综合系统处理
            try {
                R<Boolean> booleanR = serviceOrderFeign.updateBizRefundState(BeanUtil.copyProperties(refund, BizStateDTO.class));
                if (!booleanR.getIsSuccess()) {
                    throw BizException.wrap(booleanR.getCode(), booleanR.getMsg());
                }
            } catch (Exception e) {
                throw e;
            }
        }
    }

    /**
     * @param applyRefundDTO
     * @Author clm
     * @Description //接受退款申请
     * @Date 14:19 2023/2/20
     * @Param [applyRefundDTO]
     */
    @Override
    public void acceptApplyRefund(ApplyRefundDTO applyRefundDTO) {
        if (applyRefundDTO.getRefundApplyAmount().compareTo(new BigDecimal(0)) <= 0) {
            throw BizException.wrap(PayExceptionCode.ZERO_REFUND_NOT_ACCEPT);
        }
        TransactionOrder transactionOrder = transactionOrderService.getByOrderNum(applyRefundDTO.getBusinessNum());
        if (Objects.isNull(transactionOrder)) {
            throw BizException.wrap(PayExceptionCode.TRANSACTION_ORDER_NOT_EXIST);
        }
        if (TransactionOrderOrderStatusEnum.REFUNDED.equals(transactionOrder.getOrderStatus())) {
            throw BizException.wrap(PayExceptionCode.ORDER_REFUNDED);
        }

        if (OrderStateEnum.CANCELED.equals(transactionOrder.getState())) {
            throw BizException.wrap(PayExceptionCode.ORDER_CANCEL);
        }

        if (TransactionOrderOrderStatusEnum.REFUNDING.equals(transactionOrder.getOrderStatus())) {
            throw BizException.wrap(PayExceptionCode.ORDER_REFUNDING);
        }

        if (TransactionOrderOrderStatusEnum.UNPAY.equals(transactionOrder.getOrderStatus()) || TransactionOrderOrderStatusEnum.PAYING.equals(transactionOrder.getOrderStatus())) {
            transactionOrderService.cancel(transactionOrder.getOrderNum());
            return;
        }

        //对象实例化
        ApplyRefund applyRefund = new ApplyRefund();
        //对象复制
        BeanUtils.copyProperties(applyRefundDTO, applyRefund);
        applyRefund.setSystemCode(ContextUtil.getSystemScene());
        applyRefund.setPayOrderNo(transactionOrder.getPayOrderNo());
        if (StringUtils.isBlank(applyRefund.getExhibitionName())) {
            applyRefund.setExhibitionName(transactionOrder.getExhibitionName());
        }
        if (StringUtils.isBlank(applyRefund.getMerchantName())) {
            applyRefund.setMerchantName(transactionOrder.getPayee());
        }
        if (StringUtils.isBlank(applyRefund.getBusinessNum())) {
            applyRefund.setBusinessNum(transactionOrder.getOrderNum());
        }
        if (Objects.isNull(applyRefund.getExhibitionId())) {
            applyRefund.setExamineId(transactionOrder.getExhibitionId());
        }


        if (StringUtils.isBlank(applyRefund.getExamineState())) {
            applyRefund.setExamineState(RefundExamineStateEnum.APPLIED.getCode());
        }
        if (Objects.isNull(applyRefund.getRefundState())) {
            applyRefund.setRefundState(RefundStatusEnum.UN_REFUND.getCode());
        }

        String refundType = applyRefund.getRefundType();
        if (StrUtil.isBlank(refundType)) {
            if (PayTypeEnum.TRANSFER_ACCOUNT.getCode().equals(transactionOrder.getPayType())) {
                refundType = RefundTypeEnum.PUBLIC_TO_PUBLIC.getCode();
            } else if (PayTypeEnum.CASH_PAY.getCode().equals(transactionOrder.getPayType())) {
                refundType = RefundTypeEnum.OFFLINE.getCode();
            } else {
                refundType = RefundTypeEnum.ONLINE.getCode();
            }
        }
        applyRefund.setRefundType(refundType);
        // 公对公转账退款
        if (RefundTypeEnum.PUBLIC_TO_PUBLIC.getCode().equals(refundType)) {
            // 获取认款金额
            BigDecimal collectAmount = collectRecordService.calSumAmountByOrderNum(applyRefund.getBusinessNum());
            if (applyRefund.getRefundApplyAmount().compareTo(collectAmount) > 0) {
                throw BizException.wrap(PayExceptionCode.REFUND_AMOUNT_GT);
            }
            List<CollectRecord> recordList = collectRecordService.getRecordListByOrderNum(applyRefund.getBusinessNum());
            if (CollectionUtils.isNotEmpty(recordList)) {
                PaymentRecord paymentRecord = paymentRecordService.lambdaQuery().eq(PaymentRecord::getId, recordList.get(0).getPaymentRecordId()).one();
                applyRefund.setBankName(paymentRecord.getBankName());
                applyRefund.setBankAccountName(paymentRecord.getBankAccountName());
                applyRefund.setBankAccountNum(paymentRecord.getBankAccountName());
                applyRefund.setMerchantBank(paymentRecord.getBankName());
                applyRefund.setExamineState(RefundExamineStateEnum.APPLIED.getCode());
                applyRefund.setRefundState(RefundStatusEnum.UN_REFUND.getCode());
            } else {
                transactionOrderService.cancel(transactionOrder.getOrderNum());
                return;
            }
        } else if (RefundTypeEnum.ONLINE.getCode().equals(refundType)) {
            // 在线退款
            if (applyRefund.getRefundApplyAmount().compareTo(transactionOrder.getOrderAmount()) > 0) {
                throw BizException.wrap(PayExceptionCode.REFUND_AMOUNT_GT);
            }
            applyRefund.setExamineState(RefundExamineStateEnum.APPLIED.getCode());
            applyRefund.setRefundState(RefundStatusEnum.UN_REFUND.getCode());
            // 判断订单支付时间 是否是当天 当天可以走线上退款 超过0点就需要走荆艺退款
//            LocalDateTime startLine = LocalDateTimeUtil.beginOfDay(LocalDateTimeUtil.of(new Date()));
//            LocalDateTime endLine = LocalDateTimeUtil.endOfDay(LocalDateTimeUtil.of(new Date()));

            // 付款时间大于等于当天的0点 小于等于当天的23:59 可以支持线上退款
//            if ((transactionOrder.getPaymentTime().compareTo(startLine) > 0) && (transactionOrder.getPaymentTime().compareTo(endLine) <= 0)) {
//                // 调用在线退款
//                ChinaumsLogDTO chinaumsLog = new ChinaumsLogDTO();
//                chinaumsLog.setOrderNum(applyRefund.getBusinessNum());
//                chinaumsLog.setOrderType(transactionOrder.getOrderType());
//                ChinaumsLogVO refund = chinaumsLogService.refund(chinaumsLog);
//                if (refund.getIsSuccess() == 1) {
//                    // 退款成功
//                    applyRefund.setExamineState(RefundExamineStateEnum.AUTH_SUCESS.getCode());
//                    applyRefund.setRefundState(RefundStatusEnum.IS_REFUND.getCode());
//                    applyRefund.setRefundNum(refund.getRefundOrderId());
//                    applyRefund.setRefundTime(LocalDateTime.now());
//                    applyRefund.setRefundAmount(BigDecimal.valueOf(refund.getRefundAmount()));
//                    transactionOrder.setOrderStatus(TransactionOrderOrderStatusEnum.REFUNDED);
//                    transactionOrder.setState(OrderStateEnum.COMPLETED.getCode());
//                    // 回写订单状态
////                    if (RefundClassifyEnum.ORDER_CANCEL.getCode().equals(applyRefund.getRefundClassify())) {
////                        transactionOrder.setState(OrderStateEnum.CANCELED.getCode());
////                        transactionOrderService.cancel(transactionOrder.getOrderNum());
////                    } else {
////                        transactionOrder.setState(OrderStateEnum.COMPLETED.getCode());
////                    }
//                } else {
//                    // 退款失败
//                    applyRefund.setExamineState(RefundExamineStateEnum.AUTH_ERROR.getCode());
//                    applyRefund.setRefundState(RefundStatusEnum.UN_REFUND.getCode());
//                    applyRefund.setIsEnabled(BusinessConstant.ENABLE_NO);
//                    applyRefund.setRefundNum(refund.getRefundOrderId());
//                }
//            } else {
//                // 超过可以线上退款的时间范围，走财务退款退款 审核时候需要补充信息
//                applyRefund.setExamineState(RefundExamineStateEnum.APPLIED.getCode());
//                applyRefund.setRefundState(RefundStatusEnum.UN_REFUND.getCode());
//            }

        } else {
            // 线下退款
            if (applyRefund.getRefundApplyAmount().compareTo(transactionOrder.getOrderAmount()) > 0) {
                throw BizException.wrap(PayExceptionCode.REFUND_AMOUNT_GT);
            }
            applyRefund.setExamineState(RefundExamineStateEnum.APPLIED.getCode());
            applyRefund.setRefundState(RefundStatusEnum.UN_REFUND.getCode());
        }
        //保存退款申请
        save(applyRefund);
        transactionOrderService.updateById(transactionOrder);
        // 修改业务表退款状态
        updateRefundState(applyRefund);
        log.info("更新退款同步业务系统成功");
    }

    /**
     * 修改业务表的退款状态
     *
     * @param applyRefund
     */
    private void updateRefundState(ApplyRefund applyRefund) {
        Map<String, String> map = new HashMap<>();
        map.put("APPLIED", "REQUESTED");
        map.put("AUTH_SUCESS", "REFUNDED");
        map.put("AUTH_FAIL", "REJECTED");
        map.put("AUTH", "REFUNDING");

        MenuAffiliationEnum anEnum = MenuAffiliationEnum.get(applyRefund.getSystemCode());
        log.info("归属系统:{},订单号:{},退款状态:{}", applyRefund.getSystemCode(), applyRefund.getBusinessId(), applyRefund.getRefundState());
        switch (anEnum) {
            case P_COMPOSITE_VENUE:
            case P_COMPOSITE_COURT:
            case P_COMPOSITE_PRODUCER:
            case P_COMPOSITE_TRANSPORT:
            case P_COMPOSITE_MATING:
                // 业务类型#{H:合同;J:结算单;G:管理费订单;D:服务订单;Z:证件订单;}
                // todo 待完善
                switch (applyRefund.getBusinessType()) {
                    case "J":
                        ExhibitionSettlementDTO settlementDTO = new ExhibitionSettlementDTO();
                        settlementDTO.setId(applyRefund.getBusinessId());
                        settlementDTO.setRefundStatus(ExhibitionSettlementRefundStatusEnum.valueOf(map.get(applyRefund.getExamineState())));
                        exhibitionSettlementFeign.updateSettlement(settlementDTO);
                        break;
                    case "H":
                        break;
                    case "G":
                    case "D":
                        // 管理费、服务订单
                        ServiceOrderDTO serviceOrderDTO = new ServiceOrderDTO();
                        serviceOrderDTO.setOrderNumber(applyRefund.getBusinessNum());
                        serviceOrderDTO.setRefundStatus(applyRefund.getExamineState());
                        serviceOrderDTO.setRefundWay(applyRefund.getRefundType());
                        if (RefundExamineStateEnum.AUTH_SUCESS.getCode().equals(applyRefund.getExamineState())) {
                            serviceOrderDTO.setRefundTime(applyRefund.getRefundTime());
                            serviceOrderDTO.setRefundAmount(applyRefund.getRefundAmount());
                        }
                        Request.Options options = new Request.Options(1L, TimeUnit.MINUTES, 1L, TimeUnit.MINUTES, true);
                        serviceOrderFeign.updateRefundStatus(serviceOrderDTO, options);
                        break;
                    case "B":
                        BondManageDTO bondManageDTO = new BondManageDTO();
                        bondManageDTO.setOrderNumber(applyRefund.getBusinessNum());
                        bondManageDTO.setRefundWay(applyRefund.getRefundType());
                        bondManageDTO.setRefundStatus(applyRefund.getExamineState());
                        if (RefundExamineStateEnum.AUTH_SUCESS.getCode().equals(applyRefund.getExamineState())) {
                            bondManageDTO.setActualRefundAmount(applyRefund.getRefundAmount());
                            bondManageDTO.setRefundTime(applyRefund.getRefundTime());
                        }
                        bondManageFeign.updateRefundStatus(bondManageDTO);
                        break;
                    case "Z":
                        break;
                    default:
                        log.info("未知业务类型");
                }
                break;
            case P_VENUE:
                switch (applyRefund.getBusinessType()) {
                    case "J":
                        //查询结算单
                        Settlement settlement = settlementService.getById(applyRefund.getBusinessId());
                        if (null == settlement) {
                            throw BizException.wrap(PayExceptionCode.SETTLEMEN_DOCUMENT_DOES_NOT_EXIST);
                        }
                        //修正已退金额
//                        settlement.setReturnedAmount(applyRefund.getRefundApplyAmount().add(settlement.getReturnedAmount()));
                        settlement.setRefundApplyStatus(map.get(applyRefund.getExamineState()));
                        //修正结算退款金额
                        settlementService.updateById(settlement);
                        break;
                    case "H":
                        break;
                    case "G":
                    case "D":
                        // 管理费、服务订单
                        ServiceOrderDTO serviceOrderDTO = new ServiceOrderDTO();
                        serviceOrderDTO.setOrderNumber(applyRefund.getBusinessNum());
                        serviceOrderDTO.setRefundStatus(applyRefund.getExamineState());
                        if (RefundExamineStateEnum.AUTH_SUCESS.getCode().equals(applyRefund.getExamineState())) {
                            serviceOrderDTO.setRefundTime(applyRefund.getRefundTime());
                            serviceOrderDTO.setRefundAmount(applyRefund.getRefundAmount());
                        }
                        Request.Options options = new Request.Options(1L, TimeUnit.MINUTES, 1L, TimeUnit.MINUTES, true);
                        serviceOrderFeign.updateRefundStatus(serviceOrderDTO, options);
                        break;
                    case "Z":
                        break;
                    default:
                        log.info("未知业务类型");
                }

            default:
                log.info("未同步的系统:{},订单号:{},开票状态:{}", applyRefund.getSystemCode(), applyRefund.getBusinessId(), applyRefund.getRefundState());
        }
    }

    /**
     * @param applyRefundDTO
     * @return
     * @Author clm
     * @Description //更新
     * @Date 14:38 2023/2/20
     * @Param
     */
    @Override
    public void updateApplyRefund(ApplyRefundDTO applyRefundDTO) {
        //对象实例化
        ApplyRefund applyRefund = new ApplyRefund();
        //对象复制
        BeanUtils.copyProperties(applyRefundDTO, applyRefund);
        updateById(applyRefund);
    }

    /**
     * @return
     * @Author clm
     * @Description //获取退款总金额
     * @Date 11:14 2023/2/24
     * @Param []
     **/
    @Override
    public BigDecimal getRefundTotalAmount() {

        BigDecimal refundTotalAmount = baseMapper.getRefundTotalAmount();

        return refundTotalAmount == null ? new BigDecimal(0) : refundTotalAmount;
    }

    /**
     * @return
     * @Author clm
     * @Description //财务审核
     * @Date 11:14 2023/3/3
     * @Param []
     **/
    @Override
    public void financialExamine(ApplyRefundDTO applyRefundDTO) {
        if (StringUtils.isBlank(applyRefundDTO.getMainno()) || applyRefundDTO.getRefundState() == null) {
            throw new BizException("参数不能为空");
        }
        ContextUtil.setProjectId(projectId);

        LambdaQueryWrapper<ApplyRefund> query = new LambdaQueryWrapper<>();
        query.eq(ApplyRefund::getMainno, applyRefundDTO.getMainno());

        List<ApplyRefund> list = baseMapper.selectList(query);
        if (CollectionUtils.isEmpty(list)) {
            throw new BizException("退款申请不存在");
        }
        ApplyRefund applyRefund = list.get(0);

        TransactionOrder transactionOrder = transactionOrderService.getByOrderNum(applyRefund.getBusinessNum());
        if (Objects.isNull(transactionOrder)) {
            throw new BizException("交易订单不存在");
        }
        log.info("退款申请记录,applyRefund={}", applyRefund);
        applyRefund.setRefundState(applyRefundDTO.getRefundState());
        applyRefund.setRefundTime(applyRefundDTO.getRefundTime());
        // 退款成功
        if (RefundStatusEnum.IS_REFUND.getCode().equals(applyRefundDTO.getRefundState())) {
            applyRefund.setRefundNum(applyRefundDTO.getMainno());
            applyRefund.setExamineState(RefundExamineStateEnum.AUTH_SUCESS.getCode());
            applyRefund.setRefundTime(LocalDateTime.now());
            if (Objects.isNull(applyRefund.getRefundAmount())) {
                applyRefund.setRefundAmount(applyRefund.getRefundApplyAmount());
            }
            transactionOrder.setOrderStatus(TransactionOrderOrderStatusEnum.REFUNDED);
            transactionOrder.setState(OrderStateEnum.COMPLETED.getCode());
            // 回写订单状态
//            if (RefundClassifyEnum.ORDER_CANCEL.getCode().equals(applyRefund.getRefundClassify())) {
//                transactionOrder.setState(OrderStateEnum.CANCELED.getCode());
//                transactionOrderService.cancel(transactionOrder.getOrderNum());
//            } else {
//                transactionOrder.setState(OrderStateEnum.COMPLETED.getCode());
//            }
            log.info("退款成功,transactionOrder={}", transactionOrder);
        } else {
            // 退款失败
            applyRefund.setRefundNum(applyRefundDTO.getMainno());
            applyRefund.setExamineState(RefundExamineStateEnum.AUTH_ERROR.getCode());
            applyRefund.setRefundState(RefundStatusEnum.UN_REFUND.getCode());
            applyRefund.setIsEnabled(BusinessConstant.ENABLE_NO);
            log.info("退款失败,transactionOrder={}", transactionOrder);
        }
        updateById(applyRefund);
        transactionOrderService.updateById(transactionOrder);
        updateRefundState(applyRefund);
        log.info("退款状态同步业务系统成功");
        log.info("退款审核结果,applyRefund={}", applyRefund);
    }


    @Override
    public List<ApplyRefundVO> queryRefundExamineState(List<Long> buinessIds) {
        log.info("参数：buinessIds={}", buinessIds);
        if (CollectionUtils.isEmpty(buinessIds)) {
            throw new BizException("参数不合法");
        }
        List<ApplyRefund> modelList = applyRefundMapper.queryRefundExamineStateByIds(buinessIds);
        if (CollectionUtils.isEmpty(modelList)) {
            return Lists.newArrayList();
        } else {
            return modelList.stream().map(m -> {
                ApplyRefundVO applyRefundVO = new ApplyRefundVO();
                applyRefundVO.setBusinessId(m.getBusinessId());
                applyRefundVO.setExamineState(m.getExamineState());
                applyRefundVO.setId(m.getId());
                return applyRefundVO;
            }).collect(Collectors.toList());
        }
    }

    @Override
    public Boolean onlineRefund(RefundDTO dto) {
        ApplyRefund applyRefund = lambdaQuery().eq(ApplyRefund::getBusinessNum, dto.getOrderNum())
                .eq(ApplyRefund::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(ApplyRefund::getIsEnabled, BusinessConstant.ENABLE_YES).one();
        if (Objects.isNull(applyRefund)) {
            throw BizException.wrap(PayExceptionCode.APPLY_REFUND_DOES_NOT_EXIST);
        }
        // 退款成功
        applyRefund.setRefundState(dto.getRefundStatus().getCode());
        applyRefund.setRefundNum(dto.getTransactionSerialNum());
        applyRefund.setRefundTime(dto.getRefundTime());
        if (RefundStatusEnum.IS_REFUND.equals(dto.getRefundStatus())) {
            applyRefund.setExamineState(RefundExamineStateEnum.AUTH_SUCESS.getCode());
        }
        updateById(applyRefund);
        return true;
    }
}
